package com.ink.grib;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.cron.CronUtil;
import cn.hutool.cron.task.Task;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.ink.grib.model.Grib2JsonOptions;
import net.nullschool.grib2json.Grib2Json;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @author LJK
 */
public class GribToJsonTask {
    /**
     * 文件保存地址
     */
    private static final String FILE_SAVE_PATH = "/ink/data";

    public static void main(String[] args) {
        // 立即执行一次
        System.out.println("[启动完成] 程序启动完成, 开始执行第一次任务!");
        new GribToJsonTask().runTask();
        // 开启定时任务
        CronUtil.schedule("0 0 0/3 * * ?", (Task) () -> new GribToJsonTask().runTask());
        CronUtil.start();
    }

    /**
     * 获取数据列表
     *
     * @param home home时间
     * @param hour 小时
     * @return 结果
     */
    private static List<String> getDataList(String home, String hour) {
        List<String> dataList = new ArrayList<>();
        String url = "https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?dir=/gfs.{}/{}/atmos";
        url = StrUtil.format(url, home, hour);
        String rest1 = HttpRequest.get(url).timeout(20000).execute().body();
        if (StrUtil.isBlank(rest1)) {
            return null;
        }

        if (rest1.contains("<select")) {
            rest1 = rest1.substring(rest1.indexOf("<select"), rest1.indexOf("</select>") + 9);
            // 处理格式错误点
            rest1 = rest1.replaceAll("&nbsp;", "");
            rest1 = rest1.replaceAll("&nbsp", "");

            int s = rest1.indexOf("> gfs.");
            int e = rest1.indexOf(" (");
            while (s != -1 && e != -1) {
                String res = rest1.substring(s + 2, e);
                dataList.add(res);
                s = rest1.indexOf("> gfs.", e);
                e = rest1.indexOf(" (", (e + 2));
            }
        }

        return dataList;
    }

    /**
     * 获取最新天数文件夹
     *
     * @return 结果
     */
    public static List<String> getHomeList() {
        String rest1 = HttpRequest.get("https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl").timeout(20000).execute().body();
        if (StrUtil.isBlank(rest1)) {
            return null;
        }
        // 处理格式错误点
        rest1 = rest1.replaceAll("&nbsp;", "");
        rest1 = rest1.replaceAll("&nbsp", "");
        List<String> homeList = new ArrayList<>();
        // 取出 第一项
        int s = rest1.indexOf("<a");
        int e = rest1.indexOf("</a>");
        while (s != -1 && e != -1) {
            String res = rest1.substring(s, e + 4);
            res = res.substring(res.indexOf(">gfs."));
            res = res.substring(5, res.indexOf("</a>"));
            homeList.add(res);
            s = rest1.indexOf("<a", e);
            e = rest1.indexOf("</a>", (e + 4));
        }
        return homeList;
    }

    /**
     * 获取最新小时文件夹
     *
     * @return 结果
     */
    public static List<String> getHourList(String time) {
        String rest1 = HttpRequest.get("https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?dir=/gfs." + time).timeout(20000).execute().body();
        if (StrUtil.isBlank(rest1)) {
            return null;
        }
        // 处理格式错误点
        rest1 = rest1.replaceAll("&nbsp;", "");
        rest1 = rest1.replaceAll("&nbsp", "");
        List<String> hourList = new ArrayList<>();
        // 取出 第一项
        int s = rest1.indexOf("<a");
        int e = rest1.indexOf("</a>");
        while (s != -1 && e != -1) {
            String res = rest1.substring(s, e + 4);
            res = res.substring(res.indexOf(">"));
            res = res.substring(1, res.indexOf("</a>"));
            hourList.add(res);
            s = rest1.indexOf("<a", e);
            e = rest1.indexOf("</a>", (e + 4));
        }
        return hourList;
    }

    public void runTask() {
        System.out.println("--- [" + new Date() + "] --------------------");
        // 请求顶级列表
        List<String> homeList = getHomeList();
        if (homeList == null || homeList.size() <= 0) {
            System.out.println("无法获取最顶级日期列表!!!");
            System.out.println("--- END -------------------------------------");
            return;
        }

        List<String> dataList = null;

        boolean continueTo = true;
        String homeStr = "";
        String hourStr = "";
        for (String homeItem : homeList) {
            // 请求小时列表
            List<String> hourList = getHourList(homeItem);
            if (hourList == null || hourList.size() <= 0) {
                continue;
            }
            for (String hourItem : hourList) {
                // 请求数据列表
                System.out.println("[获取数据] 开始请求: " + homeItem + " : " + hourItem);
                homeStr = homeItem;
                hourStr = hourItem;
                dataList = getDataList(homeItem, hourItem);
                if (dataList == null || dataList.size() <= 0) {
                    continue;
                }
                continueTo = false;
                break;
            }
            if (!continueTo) {
                break;
            }
        }
        if (dataList == null || dataList.size() <= 0) {
            System.out.println("所有数据都为空!!!");
            System.out.println("--- END -------------------------------------");
            return;
        }

        // 删除第一项
        dataList.remove(0);

        // 解析数据 拉取最近24小时预测数据
        for (String dataItem : dataList) {
            String dataItemTime = StrUtil.sub(dataItem, -3, dataItem.length());
            int dataTime = Integer.parseInt(dataItemTime);
            if (dataTime <= 24) {
                // 当前请求时间 + 数据小时 + 8 = 正确时间
                String homeStr2 = StrUtil.format("{}_{}", homeStr, hourStr);
                Date date = DateUtil.parse(homeStr2, "yyyyMMdd_HH");
                DateTime zzsj = DateUtil.offsetHour(date, dataTime + 8);

                String formatNameDay = DateUtil.format(zzsj, "yyyyMMdd");
                String formatNameHour = DateUtil.format(zzsj, "HH");

                // 下载文件
                String url = "https://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?file={}&lev_10_m_above_ground=on&var_UGRD=on&var_VGRD=on&subregion&leftlon=60&rightlon=150&toplat=60&bottomlat=0&dir=/gfs.{}/{}/atmos";
                url = StrUtil.format(url, dataItem, homeStr, hourStr);
                String filePath = FILE_SAVE_PATH + File.separator + formatNameDay + File.separator;
                String wjPath = filePath + formatNameHour;
                long size = HttpUtil.downloadFile(url, FileUtil.file(wjPath));
                System.out.println(dataItem + ": " + formatNameDay + "_" + formatNameHour + " - size: " + size);

                // 开始 转 json
                File inFile = new File(wjPath);
                File outFile = new File(filePath + formatNameHour + ".json");

                Grib2JsonOptions grib2JsonOptions = new Grib2JsonOptions();
                grib2JsonOptions.setFilterParameter("wind");
                grib2JsonOptions.setFilterSurface(103);
                grib2JsonOptions.setFilterValue(10D);
                grib2JsonOptions.setFilterCategory(2);
                grib2JsonOptions.setOutput(outFile);
                grib2JsonOptions.setCompactFormat(true);
                Grib2Json grib2Json = new Grib2Json(inFile, Collections.singletonList(grib2JsonOptions));
                try {
                    grib2Json.write();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                // 删除原文件
                FileUtil.del(wjPath);
            } else {
                break;
            }
        }

        System.out.println("--- END -------------------------------------");
    }
}
